/*
 * Copyright The Stargate Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package io.stargate.sgv2.docsapi.service.write.db;

import io.stargate.bridge.grpc.Values;
import io.stargate.bridge.proto.QueryOuterClass;
import io.stargate.bridge.proto.QueryOuterClass.BatchQuery;
import io.stargate.bridge.proto.QueryOuterClass.Value;
import io.stargate.sgv2.api.common.cql.builder.BuiltCondition;
import io.stargate.sgv2.api.common.cql.builder.Predicate;
import io.stargate.sgv2.api.common.cql.builder.QueryBuilder;
import io.stargate.sgv2.api.common.cql.builder.Term;
import io.stargate.sgv2.docsapi.api.properties.document.DocumentProperties;
import java.util.ArrayList;
import java.util.List;

public abstract class AbstractDeleteQueryBuilder {

  protected final DocumentProperties documentProperties;

  protected AbstractDeleteQueryBuilder(DocumentProperties documentProperties) {
    this.documentProperties = documentProperties;
  }

  /** Adds custom conditions to the generated query. */
  protected abstract void addWhereConditions(List<BuiltCondition> whereConditions);

  /**
   * Adds any necessary bind values for the conditions generated by {@link
   * #addWhereConditions(List)}, in the same order.
   */
  protected abstract void addBindValues(List<Value> values);

  public final BatchQuery buildAndBind(
      String keyspace, String table, String documentId, long timestamp) {
    return bind(buildQuery(keyspace, table), documentId, timestamp);
  }

  public final BatchQuery buildQuery(String keyspace, String table) {
    List<BuiltCondition> whereConditions = new ArrayList<>();
    whereConditions.add(
        BuiltCondition.of(
            documentProperties.tableProperties().keyColumnName(), Predicate.EQ, Term.marker()));

    addWhereConditions(whereConditions);

    return new QueryBuilder()
        .delete()
        .from(keyspace, table)
        .timestamp()
        .where(whereConditions)
        .buildForBatch();
  }

  /**
   * Binds the query built with this query builder from supplied data.
   *
   * @param builtQuery Prepared query built by this query builder.
   * @param documentId The document id the row is inserted for.
   * @param timestamp Timestamp
   * @return Bound query.
   */
  public final BatchQuery bind(BatchQuery builtQuery, String documentId, long timestamp) {
    List<Value> values = new ArrayList<>();
    values.add(Values.of(timestamp));
    values.add(Values.of(documentId));

    addBindValues(values);

    return BatchQuery.newBuilder(builtQuery)
        .setValues(QueryOuterClass.Values.newBuilder().addAllValues(values))
        .build();
  }
}
